// 参考: https://elixir.bootlin.com/linux/v5.10.10/source/fs/ramfs/inode.c
// [mount 过程](https://qiankunli.github.io/2018/05/19/linux_file_system.html)
// [Linux内核源代码情景分析-特殊文件系统/proc](https://blog.csdn.net/jltxgcy/article/details/44858817)
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/pagemap.h>
#include <linux/mount.h>
#include <linux/init.h>
#include <linux/namei.h>
#include <linux/fs_context.h>

#define DEMOVFS_MAGIC	0x64626720
#define DEMOVFS_DEFAULT_MODE	0755

static struct super_block *mnt_sb;
static struct vfsmount *demovfs_mnt;
static int demovfs_count;

// https://elixir.bootlin.com/linux/v5.10.10/source/fs/ramfs/inode.c#L63
static struct inode *demovfs_get_inode(struct super_block *sb,
										const struct inode *dir, umode_t mode, dev_t dev)
{
	struct inode *inode = new_inode(sb); // inode会加入sb的inode链表, 这样通过sb的inode链表即可遍历fs内所有的inode结构. 同时inode会加入全局链表inode_in_use, 表示该inode使用中.

	if (inode) {
		inode->i_ino = get_next_ino();
		inode_init_owner(inode, dir, mode);
		inode->i_blocks = 0;
		inode->i_atime = inode->i_mtime = inode->i_ctime = current_time(inode);
		switch (mode & S_IFMT) { // 根据inode类型, 设置不同的操作函数
		default:
			init_special_inode(inode, mode, dev); // 针对特殊inode, 比如块设备文件或字符设备文件, 调用init_special_inode赋值.
			break;
		case S_IFREG:
			printk("creat a file \n");
			break;
		case S_IFDIR:
			inode->i_op = &simple_dir_inode_operations;
			inode->i_fop = &simple_dir_operations;
			printk("creat a dir file \n");
			/* directory inodes start off with i_nlink == 2 (for "." entry) */
			inc_nlink(inode);
			break;
		}
	}
	return inode; 
}


// https://elixir.bootlin.com/linux/v5.10.10/source/fs/ramfs/inode.c#L104
/* SMP-safe */
// dev=0 表示虚拟设备
// 作用创建inode
static int demovfs_mknod(struct inode *dir, struct dentry *dentry,
			 umode_t mode, dev_t dev)
{
	struct inode * inode = demovfs_get_inode(dir->i_sb, dir, mode, dev);
	int error = -ENOSPC;

	if (inode) {
		d_instantiate(dentry, inode); // 把dentry加入inode的dentry链表头
		dget(dentry);	/* Extra count - pin the dentry in core */
		error = 0;
		dir->i_mtime = dir->i_ctime = current_time(dir);
	}
	return error;
}


static int demovfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
{
	int retval = demovfs_mknod(dir, dentry, mode | S_IFDIR, 0);
	if (!retval)
		inc_nlink(dir);
	return retval;
}

static int demovfs_create(struct inode *dir, struct dentry *dentry, int mode)
{
	return demovfs_mknod(dir, dentry, mode | S_IFREG, 0);
}

// static struct super_block *demovfs_get_sb(struct file_system_type *fs_type,
// 				        int flags, const char *dev_name,
// 					void *data)
// {
// 	return get_sb_single(fs_type, flags, data, demovfs_fill_super);
// }

// 作用: 创建文件的dentry和inode.
static int demovfs_create_by_name(const char *name, mode_t mode,
				  struct dentry *parent,
				  struct dentry **dentry)
{
	int error = 0;
	printk("demovfs: demovfs_create_by_name start '%s'\n",name);

	/* If the parent is not specified, we create it in the root.
	 * We need the root dentry to do this, which is in the super 
	 * block. A pointer to that is in the struct vfsmount that we
	 * have around.
	 */
	if (!parent) {
		if (mnt_sb && mnt_sb->s_root) {
			parent = mnt_sb->s_root;
		}
	}
	if (!parent) {
		printk("demovfs: Ah! can not find a parent!\n");
		return -EFAULT;
	}

	*dentry = NULL;
	inode_lock(parent->d_inode); // https://elixir.bootlin.com/linux/v5.12.9/source/fs/afs/dynroot.c#L306
	*dentry = lookup_one_len(name, parent, strlen(name)); // 检查名为name的目录是否存在. lookup_one_len在父目录下根据名称查找dentry, 存在返回指针, 不存在则创建一个.
	if (!IS_ERR(dentry)) {
		if ((mode & S_IFMT) == S_IFDIR)
			error = demovfs_mkdir(parent->d_inode, *dentry, mode);
		else 
			error = demovfs_create(parent->d_inode, *dentry, mode);
	} else
		error = PTR_ERR(dentry);
	inode_unlock(parent->d_inode);

	printk("demovfs: demovfs_create_by_name done '%s'\n",name);

	return error;
}

struct dentry *demovfs_create_file(const char *name, mode_t mode,
				   struct dentry *parent, void *data,
				   struct file_operations *fops)
{
	struct dentry *dentry = NULL;
	int error;

	printk("demovfs: creating file '%s'\n",name);

	error = demovfs_create_by_name(name, mode, parent, &dentry);
	if (error) {
		dentry = NULL;
		goto exit;
	}

	if (dentry->d_inode) {
		if (data)
			dentry->d_inode->i_private = data; // https://asterisk-users.digium.narkive.com/6glCCvoz/make-zaptel-1-2-16-struct-inode-has-no-member-named-u
		if (fops)
			dentry->d_inode->i_fop = fops;
	}
exit:
	printk("demovfs: created file '%s, %p'\n",name, dentry);
	return dentry;
}

	
struct dentry *demovfs_create_dir(const char *name, struct dentry *parent)
{
	struct dentry *dentry = NULL;
	printk("demovfs: creating dir '%s'\n",name);

	dentry = demovfs_create_file(name,
				   S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO,
				   parent, NULL, NULL);
	printk("demovfs: created dir '%s'\n",name);
	return dentry;
}

static void generate_demo_fs(void)
{
    struct dentry *pslot;

    pslot = demovfs_create_dir("woman star", NULL);
	demovfs_create_file("lbb", S_IFREG | S_IRUGO, pslot, NULL, NULL);
    demovfs_create_file("fbb", S_IFREG | S_IRUGO, pslot, NULL, NULL);
    demovfs_create_file("ljl", S_IFREG | S_IRUGO, pslot, NULL, NULL);
    
    pslot = demovfs_create_dir("man star", NULL);
	demovfs_create_file("ldh", S_IFREG | S_IRUGO, pslot, NULL, NULL);
    demovfs_create_file("lcw", S_IFREG | S_IRUGO, pslot, NULL, NULL);
    demovfs_create_file("jw", S_IFREG | S_IRUGO, pslot, NULL, NULL);
}

// 真实fs mount流程： [vfs_kern_mount](https://elixir.bootlin.com/linux/v5.12.9/source/fs/namespace.c#L1002) -> fs_context_for_mount(type, flags); ... fc_mount(fc) -> vfs_create_mount 的 `mnt->mnt.mnt_sb		= fc->root->d_sb;`
// static struct dentry *demovfs_mount(struct file_system_type *fs_type,
// 				        int flags, const char *dev_name, void *data)
// {
// 	printk("demovfs_mount starting\n");
// 	printk(KERN_ERR "%s failed with args (%p, %d, %p, %p)\n",
// 			__func__, fs_type, flags, dev_name, data);

// 	struct dentry *d = mount_bdev(fs_type, flags, dev_name, data, demovfs_fill_super); // mount_bdev函数主要完成superblock对象的内存初始化，并且加入到全局superblock链表中
// 	printk(KERN_ERR "%s dentry (%p)\n",
// 			__func__, d);

// 	if (!d) {
// 		printk(KERN_ERR "%s failed while demovfs_mount\n",
// 			__func__);
// 		return NULL;
// 	}

// 	mnt_sb = d->d_sb;
//     // generate_demo_fs();

//     return d;
// }

// static int aufs_fill_super(struct super_block *sb, void *data, int silent)
// {
// 	static struct tree_descr debug_files[] = {{""}}; // tree_descr用于描述一些文件. 如果不为空, 则填充super_block时还会在该fs根目录下创建一些文件.

// 	return simple_fill_super(sb, AUFS_MAGIC, debug_files);
// }

static int demovfs_fill_super(struct super_block *sb, struct fs_context *fc)
{
	printk("%s starting with args (%p, %p)\n",
			__func__, sb, fc);

	struct inode *inode;
	sb->s_maxbytes		= MAX_LFS_FILESIZE;
	sb->s_blocksize		= PAGE_SIZE;
	sb->s_blocksize_bits	= PAGE_SHIFT;
	sb->s_magic		= DEMOVFS_MAGIC;

	inode = demovfs_get_inode(sb, NULL, S_IFDIR| DEMOVFS_DEFAULT_MODE, 0);
	sb->s_root = d_make_root(inode);
	if (!sb->s_root)
		return -ENOMEM;

	printk("demovfs: set mnt_sb (%p, %p)\n", sb, sb->s_root);
	mnt_sb = sb;
    generate_demo_fs();

	return 0;
}

static int demovfs_get_tree(struct fs_context *fc)
{
	printk("demovfs_get_tree starting\n");
	return get_tree_nodev(fc, demovfs_fill_super);
}

// https://elixir.bootlin.com/linux/v5.10.10/source/fs/ramfs/inode.c#L247
static void demovfs_free_fc(struct fs_context *fc)
{
	printk("demovfs_free_fc starting\n");
	return;
}

static const struct fs_context_operations demovfs_fs_context_ops = {
	.free			= demovfs_free_fc,
	.get_tree		= demovfs_get_tree,
};

int demovfs_init_fs_context(struct fs_context *fc)
{
	printk("demovfs_init_fs_context starting\n");
	fc->ops = &demovfs_fs_context_ops;
	return 0;
}

static struct file_system_type au_fs_type = {
	.owner =	THIS_MODULE,
	.name =		"demovfs",
	.init_fs_context = demovfs_init_fs_context,
	//.mount =	demovfs_mount, // 类似 2.6.18中的get_sb. 因为demovfs是虚拟fs， 不能用mount_bdev挂载
	.kill_sb =	kill_litter_super,
    .fs_flags	= FS_USERNS_MOUNT,
};
MODULE_ALIAS_FS("demovfs");

// https://elixir.bootlin.com/linux/v5.10.10/source/mm/shmem.c#L3990
static int __init demovfs_init(void)
{
	int error;
	
	error = register_filesystem(&au_fs_type); // //向系统注册"demovfs"这么一种文件系统

	if (!error) {
		printk("demovfs register filesystem done\n");
		// 使用kern_mount后会导致引用计数+1，从而rmmod无法卸载(即mount/umount后引用计数为1, 表示mod还在被使用无法卸载)
        // 虚拟fs使用kern_mount挂载
		// demovfs_mnt = kern_mount(&au_fs_type); // kern_mount真正为文件系统分配了超级块对象和vfsmount对象 // https://elixir.bootlin.com/linux/v5.12.9/source/fs/nsfs.c#L17
		// if (IS_ERR(demovfs_mnt)) {
		// 	printk(KERN_ERR "demovfs: could not mount!\n");
		// 	unregister_filesystem(&au_fs_type);
		// 	return error;
		// }
	}

	return error;
}

static void __exit demovfs_exit(void)
{
	simple_release_fs(&demovfs_mnt, &demovfs_count);
	unregister_filesystem(&au_fs_type);
}

module_init(demovfs_init);
module_exit(demovfs_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("");
MODULE_DESCRIPTION("This is a simple module");
MODULE_VERSION("Ver 0.1");

